

# 1. 获得每周期可用股票列表
#  a. 获得某日期点下全部股票列表
#  b. 获得每只股票对应的ipo时间
#  c. 如果ipo时间距离小于设定值（100天），则从列表中删除该股票
#  d. 获得经过删除后股票列表在某时间点下的交易状态
#  e. 如果交易状态不是‘交易’的股票，则从列表中删除该股票

from pymongo import MongoClient

from dateutil.relativedelta import relativedelta

import datetime

import math

import pandas as pd

from pandas import DataFrame,Series

import time

import csv

import os



from PeriodFactorGeneralFunctions import PeriodFactorGeneralFunctions

class CreatePeriodDatase:
    def __init__(self):
        periodFactorFuncObj = PeriodFactorGeneralFunctions()
        self.fillType = periodFactorFuncObj.fillType

        self.DBIP = periodFactorFuncObj.DBIP
        self.DBPort = periodFactorFuncObj.DBPort

        self.BasisDB = 'stocks'


        self.colAllStockIDName = 'daily_close'
        self.colIpoDateName = 'ipo_date'
        self.colTradeStatus = 'trade_status'
        self.colTransDates = 'trans_dates'

        self.strYieldClass = 'yield'

        self.strFileBaseFolder = 'D:\\rongshiFeatureSets1709\\'


        self.IpoDayThresholdNum = 90


        self.listKeyName2 = ['mkt_freeshares', '1M_mmt', 'mfd_buyamt_d4']
        self.listKeyName3 = ['mkt_freeshares', '1M_mmt', 'mfd_buyamt_d1']
        self.listKeyName4 = ['ev', '1M_mmt', 'mfd_buyamt_d4']
        self.listKeyName5 = ['ev', '1M_mmt', 'mfd_buyamt_d1']
        self.listKeyName6 = ['mkt_freeshares', '1M_mmt', 'reciprocal_pe_ttm']
        self.listKeyName7 = ['mkt_freeshares', 'mfd_buyamt_d4', 'reciprocal_pe_ttm']
        self.listKeyName8 = ['mkt_freeshares', 'mfd_buyamt_d1', 'reciprocal_pe_ttm']
        self.listKeyName9 = ['ev', '1M_mmt', 'reciprocal_pe_ttm']
        self.listKeyName10 = ['ev', 'mfd_buyamt_d4', 'reciprocal_pe_ttm']
        self.listKeyName11 = ['ev', 'mfd_buyamt_d1', 'reciprocal_pe_ttm']
        self.listKeyName12 = ['mkt_freeshares', '1M_mmt', 'mfd_buyamt_d4', 'reciprocal_pe_ttm']
        self.listKeyName13 = ['mkt_freeshares', '1M_mmt', 'mfd_buyamt_d1', 'reciprocal_pe_ttm']
        self.listKeyName14 = ['ev', '1M_mmt', 'mfd_buyamt_d4', 'reciprocal_pe_ttm']
        self.listKeyName15 = ['ev', '1M_mmt', 'mfd_buyamt_d1', 'reciprocal_pe_ttm']

        self.dictFeatureSet = {}
        self.dictFeatureSet['2'] = self.listKeyName2
        self.dictFeatureSet['3'] = self.listKeyName3
        self.dictFeatureSet['4'] = self.listKeyName4
        self.dictFeatureSet['5'] = self.listKeyName5
        self.dictFeatureSet['6'] = self.listKeyName6
        self.dictFeatureSet['7'] = self.listKeyName7
        self.dictFeatureSet['8'] = self.listKeyName8
        self.dictFeatureSet['9'] = self.listKeyName9
        self.dictFeatureSet['10'] = self.listKeyName10
        self.dictFeatureSet['11'] = self.listKeyName11
        self.dictFeatureSet['12'] = self.listKeyName12
        self.dictFeatureSet['13'] = self.listKeyName13
        self.dictFeatureSet['14'] = self.listKeyName14
        self.dictFeatureSet['15'] = self.listKeyName15


        self.listKeyNameTrain2 = ['mkt_freeshares', '1M_mmt', 'mfd_buyamt_d4', 'yield']
        self.listKeyNameTrain3 = ['mkt_freeshares', '1M_mmt', 'mfd_buyamt_d1', 'yield']
        self.listKeyNameTrain4 = ['ev', '1M_mmt', 'mfd_buyamt_d4', 'yield']
        self.listKeyNameTrain5 = ['ev', '1M_mmt', 'mfd_buyamt_d1', 'yield']
        self.listKeyNameTrain6 = ['mkt_freeshares', '1M_mmt', 'reciprocal_pe_ttm', 'yield']
        self.listKeyNameTrain7 = ['mkt_freeshares', 'mfd_buyamt_d4', 'reciprocal_pe_ttm', 'yield']
        self.listKeyNameTrain8 = ['mkt_freeshares', 'mfd_buyamt_d1', 'reciprocal_pe_ttm', 'yield']
        self.listKeyNameTrain9 = ['ev', '1M_mmt', 'reciprocal_pe_ttm', 'yield']
        self.listKeyNameTrain10 = ['ev', 'mfd_buyamt_d4', 'reciprocal_pe_ttm', 'yield']
        self.listKeyNameTrain11 = ['ev', 'mfd_buyamt_d1', 'reciprocal_pe_ttm', 'yield']
        self.listKeyNameTrain12 = ['mkt_freeshares', '1M_mmt', 'mfd_buyamt_d4', 'reciprocal_pe_ttm', 'yield']
        self.listKeyNameTrain13 = ['mkt_freeshares', '1M_mmt', 'mfd_buyamt_d1', 'reciprocal_pe_ttm', 'yield']
        self.listKeyNameTrain14 = ['ev', '1M_mmt', 'mfd_buyamt_d4', 'reciprocal_pe_ttm', 'yield']
        self.listKeyNameTrain15 = ['ev', '1M_mmt', 'mfd_buyamt_d1', 'reciprocal_pe_ttm', 'yield']

        self.dictTrainFeatureSet = {}
        self.dictTrainFeatureSet['2'] = self.listKeyNameTrain2
        self.dictTrainFeatureSet['3'] = self.listKeyNameTrain3
        self.dictTrainFeatureSet['4'] = self.listKeyNameTrain4
        self.dictTrainFeatureSet['5'] = self.listKeyNameTrain5
        self.dictTrainFeatureSet['6'] = self.listKeyNameTrain6
        self.dictTrainFeatureSet['7'] = self.listKeyNameTrain7
        self.dictTrainFeatureSet['8'] = self.listKeyNameTrain8
        self.dictTrainFeatureSet['9'] = self.listKeyNameTrain9
        self.dictTrainFeatureSet['10'] = self.listKeyNameTrain10
        self.dictTrainFeatureSet['11'] = self.listKeyNameTrain11
        self.dictTrainFeatureSet['12'] = self.listKeyNameTrain12
        self.dictTrainFeatureSet['13'] = self.listKeyNameTrain13
        self.dictTrainFeatureSet['14'] = self.listKeyNameTrain14
        self.dictTrainFeatureSet['15'] = self.listKeyNameTrain15


        self.percentileNumber = 1000

    def RetrieveAllStockIDList(self):
        DBIP = self.DBIP
        DBPort = self.DBPort
        DBName = self.BasisDB
        client = MongoClient(DBIP, DBPort)
        strColDailyStocks = self.colAllStockIDName
        db = client[DBName]
        collection_all_stock_id = db[strColDailyStocks]
        listStockIDs = []
        for allStockIDRes in collection_all_stock_id.find({}, {'StockID': 1, '_id': 0}):
            strStockID = allStockIDRes['StockID']
            listStockIDs.append(strStockID)
        return listStockIDs

    def RetrieveAllIpoDateDict(self):
        DBIP = self.DBIP
        DBPort = self.DBPort
        DBName = self.BasisDB
        client = MongoClient(DBIP, DBPort)
        db = client[DBName]
        strColIpoDate = self.colIpoDateName
        collection_ipo_date = db[strColIpoDate]

        ipoDateRes = collection_ipo_date.find()

        ipoDateDict = ipoDateRes[0]

        modifiedIpoDateDict = {}

        for (k, v) in ipoDateDict.items():
            k = k.replace('_', '.')
            modifiedIpoDateDict[k] = v

        return modifiedIpoDateDict

    def filterStockIdByIpoDate(self, strInputDate):
        listAllStockIDs = self.RetrieveAllStockIDList()
        dicIpoDates = self.RetrieveAllIpoDateDict()
        dtInputDate = datetime.datetime.strptime(strInputDate, "%Y%m%d")
        for (k, v) in dicIpoDates.items():
            try:
                strIpoDate = str(v)
                if str(k).find('.S') > 0:
                    ipoDate = datetime.datetime.strptime(strIpoDate, "%Y%m%d")
                    if dtInputDate < ipoDate + relativedelta(days=self.IpoDayThresholdNum):
                        listAllStockIDs.remove(k)
            except:
                next
        return listAllStockIDs

    def retrieveTradeStatusList(self, strInputDate):
        DBIP = self.DBIP
        DBPort = self.DBPort
        DBName = self.BasisDB
        client = MongoClient(DBIP, DBPort)
        strColTradeStatus = self.colTradeStatus
        db = client[DBName]

        collection_trade_status = db[strColTradeStatus]
        tradeStatusDict = {}
        temp = collection_trade_status.find({}, {'StockID': 1, '_id': 0, strInputDate:1})
        for tradeStatusRes in temp:
            try:
                tradeStatusDict[tradeStatusRes['StockID']] = tradeStatusRes[strInputDate]
            except KeyError:
                next
        return tradeStatusDict

    def filterStockIdByTradeStatus(self, strInputDate):
        listIpoFilteredStockID = self.filterStockIdByIpoDate(strInputDate)
        tradeStatusDict = self.retrieveTradeStatusList(strInputDate)
        listTradeStatusFilteredStockID = []
        for i in range(0,len(listIpoFilteredStockID)):
            try:
                if tradeStatusDict[listIpoFilteredStockID[i]] == '交易':
                    listTradeStatusFilteredStockID.append(listIpoFilteredStockID[i])
            except:
                next
        return listTradeStatusFilteredStockID

    def getOffsetInputDate(self, strInputDate, periodTypeStr, offsetDayNum):
        objPeriodFactorGenFunc = PeriodFactorGeneralFunctions()
        totalTransDateList, allPeriodPointDateList = objPeriodFactorGenFunc.RetrieveAllPeriodPointDateList(
            self.colTransDates, periodTypeStr)
        dtInputDate = datetime.datetime.strptime(strInputDate, "%Y%m%d")
        indexOfInputDate = totalTransDateList.index(dtInputDate)
        dtOutputDate = totalTransDateList[indexOfInputDate + offsetDayNum]
        strOffsetDate = dtOutputDate.strftime('%Y%m%d')
        return strOffsetDate

    def obtainOneFeature(self,strInputDate, periodTypeStr, offsetDayNum, colPeriodKeyNameMain, intQuantileNum, boolReverseCountOrder):
        strInputDate = self.getOffsetInputDate(strInputDate, periodTypeStr, offsetDayNum)
        listFilteredStockID = self.filterStockIdByTradeStatus(strInputDate)

        objPeriodFactorGenFunc = PeriodFactorGeneralFunctions()
        FactorDBName = objPeriodFactorGenFunc.ObtainOutputDBName(periodTypeStr)

        DBIP = self.DBIP
        DBPort = self.DBPort

        client = MongoClient(DBIP, DBPort)

        db = client[FactorDBName]

        colCombinedName = 'all_period_' + colPeriodKeyNameMain + '_' + periodTypeStr + '_' + str(offsetDayNum)

        collection_feature_data = db[colCombinedName]
        dictOneFeature = {}
        for featureRes in collection_feature_data.find({'StockID': {'$in': listFilteredStockID}}, {'_id': 0, 'StockID': 1, strInputDate: 1}):
        #for featureRes in collection_feature_data.find({'StockID':{'$in':['000001.SZ','000002.SZ']}}, {'_id':0, 'StockID':1, '20170630':1}):
            #print(featureRes['StockID'], featureRes[strInputDate])
            try:
                dictOneFeature[featureRes['StockID']] = featureRes[strInputDate]
            except KeyError:
                next
        if boolReverseCountOrder == True:
            sortedDict = sorted(dictOneFeature.items(), key=lambda item:item[1], reverse=True)
        else:
            sortedDict = sorted(dictOneFeature.items(), key=lambda item: item[1], reverse=False)
        stockNum = len(dictOneFeature)
        for (k, v) in dictOneFeature.items():
            t= (k,v)
            dictOneFeature[k] = math.ceil(sortedDict.index(t)/stockNum*(intQuantileNum-1))+1
        return dictOneFeature
        # for k in dictOneFeature.items():
        #     dictOneFeature[k] = sortedDict.index(k)
        # print('ok')

    def createTestingFeatureDataFileName(self,  strInputDate, periodTypeStr, offsetDayNum, intFeatureVersionNum, fileType):
        strBaseFolder = self.strFileBaseFolder
        if periodTypeStr == 'M':
            strBaseFolder = strBaseFolder + 'monthly' + '\\'
        elif periodTypeStr == 'W':
            strBaseFolder = strBaseFolder + 'weekly' + '\\'
        elif periodTypeStr == 'Q':
            strBaseFolder = strBaseFolder + 'quarterly' + '\\'

        if offsetDayNum == 0:
            strBaseFolder = strBaseFolder + 'end' + '\\'
        else:
            strBaseFolder = strBaseFolder + 'end' + str(offsetDayNum) + '\\'

        if fileType == 'testing':
            strBaseFolder =strBaseFolder + 'feature_v' + str(intFeatureVersionNum) + '\\' + fileType + '\\'

        if not os.path.isdir(strBaseFolder):
            os.makedirs(strBaseFolder)

        strFileName = self.convertInputDateStrToFileIndexDateStr(strInputDate, periodTypeStr)

        return strBaseFolder + strFileName + 'pred.csv'

    def createTrainingFeatureDataFileName(self,  strPeriodStartYearMonth, strPeriodEndYearMonth, periodTypeStr, offsetDayNum, intFeatureVersionNum, fileType, trainingPeiodNumber, intLowerLowerPercentile, intRangePercentile):
        strBaseFolder = self.strFileBaseFolder
        if periodTypeStr == 'M':
            strBaseFolder = strBaseFolder + 'monthly' + '\\'
        elif periodTypeStr == 'W':
            strBaseFolder = strBaseFolder + 'weekly' + '\\'
        elif periodTypeStr == 'Q':
            strBaseFolder = strBaseFolder + 'quarterly' + '\\'

        if offsetDayNum == 0:
            strBaseFolder = strBaseFolder + 'end' + '\\'
        else:
            strBaseFolder = strBaseFolder + 'end' + str(offsetDayNum) + '\\'

        if fileType == 'training':
            strBaseFolder =strBaseFolder + 'feature_v' + str(intFeatureVersionNum) + '\\' + fileType + '\\' + str(trainingPeiodNumber) + str.lower(periodTypeStr) + '_' + str(intLowerLowerPercentile) + '_' + str(intLowerLowerPercentile + intRangePercentile) + '\\'

        if not os.path.isdir(strBaseFolder):
            os.makedirs(strBaseFolder)

        strFileName = strPeriodStartYearMonth + '-' + strPeriodEndYearMonth + '_train.csv'

        return strBaseFolder + strFileName


    def writeOnePeriodTestingDataFile(self, strInputDate, periodTypeStr, offsetDayNum, listPeriodKeyNameMain, intQuantileNum, intFeatureVersionNum, fileType):
        dictFirstFeature = self.obtainOneFeature(strInputDate, periodTypeStr, offsetDayNum, listPeriodKeyNameMain[0], intQuantileNum, True)
        listStockID = list(dictFirstFeature.keys())
        lenStockIDNum = len(listStockID)
        featureSetList = []
        for i in range(0, lenStockIDNum):
            oneItem = []
            oneItem.append(listStockID[i] + '_' + datetime.datetime.strptime(strInputDate, "%Y%m%d").strftime('%Y-%m-%d'))
            featureSetList.append(oneItem)
        for strFeatureName in listPeriodKeyNameMain:
            dictFeature = self.obtainOneFeature(strInputDate, periodTypeStr,  offsetDayNum, strFeatureName, intQuantileNum, True)
            listFeature = list(dictFeature.values())
            for j in range(0, lenStockIDNum):
                featureSetList[j].append(listFeature[j])

        listHeader = []
        listHeader.append('id')
        for headerKeyItem in listPeriodKeyNameMain:
            listHeader.append(str(headerKeyItem))
        listHeader.append('yield_class')

        strTestingFileName = self.createTestingFeatureDataFileName(strInputDate, periodTypeStr, offsetDayNum, intFeatureVersionNum, fileType)

        with open(strTestingFileName, 'w') as csvfile:
            writer = csv.writer(csvfile, delimiter=',', lineterminator='\n')
            writer.writerow(listHeader)
            for k in range(0,lenStockIDNum):
                writer.writerow(featureSetList[k])

        print('Finished writing testing file of ' + strTestingFileName + ' of feature version number: ' + str(intFeatureVersionNum))

    def convertInputDateStrToFileIndexDateStr(self, strInputDate, periodTypeStr):
        objPeriodFactorGenFunc = PeriodFactorGeneralFunctions()
        totalTransDateList, allPeriodPointDateList = objPeriodFactorGenFunc.RetrieveAllPeriodPointDateList(self.colTransDates, periodTypeStr)
        dtInputDate = datetime.datetime.strptime(strInputDate, "%Y%m%d")
        indexOfInputDate = totalTransDateList.index(dtInputDate)
        dtFirstDayInTheNextPeriod = totalTransDateList[indexOfInputDate + 1]
        strFileName = ''
        if periodTypeStr == 'M':
            strFileName = dtFirstDayInTheNextPeriod.strftime('%Y%m')
        return strFileName



    def writeUpdateOneWholeTestingFeatureSet(self, strStartYearMonth, strEndYearMonth, periodTypeStr, offsetDayNum, listPeriodKeyNameMain, intQuantileNum, strFeatureVersionNum, fileType):
        objPeriodFactorGenFunc = PeriodFactorGeneralFunctions()
        totalTransDateList, allPeriodPointDateList = objPeriodFactorGenFunc.RetrieveAllPeriodPointDateList(self.colTransDates, periodTypeStr)
        dtStartDate = datetime.datetime.strptime(strStartYearMonth, "%Y%m")
        dtEndDate = datetime.datetime.strptime(strEndYearMonth, "%Y%m")
        listToUpdatePeriodDayList = []
        for i in range(0, len(allPeriodPointDateList)):
            if allPeriodPointDateList[i] > dtStartDate  and allPeriodPointDateList[i] < dtEndDate:
                listToUpdatePeriodDayList.append(allPeriodPointDateList[i].strftime('%Y%m%d'))
        for strInputDate in listToUpdatePeriodDayList:
            self.writeOnePeriodTestingDataFile(strInputDate, periodTypeStr, offsetDayNum, listPeriodKeyNameMain, intQuantileNum, strFeatureVersionNum, fileType)


    def writeUpdateAllTestingFeatureSet(self, strStartMonth, strEndMonth, strPeriodType, numOffsetDays):


        #############################################
        # 输入日期一定要为带预测周期的第一天（对于月换仓，不需要加日）
        #strStartMonth = '201201'
        #strEndMonth = '201707'
        # 输入日期一定要为待预测周期的第一天（对于月换仓，不需要加日）
        #############################################


        fileType = 'testing'


        for (k,v) in self.dictFeatureSet.items():

            featureVersionNum = int(k)
            listKeyName = v

            self.writeUpdateOneWholeTestingFeatureSet(strStartMonth, strEndMonth, strPeriodType, numOffsetDays, listKeyName, self.percentileNumber,
                                     featureVersionNum, fileType)
            print('Finished writing testing files of feature number:'+ k + ' , which contains:', v)


    def obtainOnePeriodTrainingDataFile(self, strInputDate, periodTypeStr, offsetDayNum, listPeriodKeyNameMain, intQuantileNum, intFeatureVersionNum, fileType, intLowerLowerPercentile, intRangePercentile):

        dictFirstFeature = self.obtainOneFeature(strInputDate, periodTypeStr, offsetDayNum, listPeriodKeyNameMain[0], intQuantileNum, True)
        listStockID = list(dictFirstFeature.keys())
        lenStockIDNum = len(listStockID)
        featureSetList = []

        lowerLower = (intLowerLowerPercentile + 1) * 10
        lowerUpper = (intLowerLowerPercentile + intRangePercentile + 1) * 10

        upperLower = (100 - intLowerLowerPercentile - intRangePercentile) * 10
        upperUpper = (100 - intLowerLowerPercentile) * 10

        for i in range(0, lenStockIDNum):
            oneItem = []
            oneItem.append(listStockID[i] + '_' + datetime.datetime.strptime(strInputDate, "%Y%m%d").strftime('%Y-%m-%d'))
            featureSetList.append(oneItem)
        for strFeatureName in listPeriodKeyNameMain:
            dictFeature = self.obtainOneFeature(strInputDate, periodTypeStr,  offsetDayNum, strFeatureName, intQuantileNum, True)
            listFeature = list(dictFeature.values())
            for j in range(0, lenStockIDNum):
                featureSetList[j].append(listFeature[j])

        listOutputFeatureSet = []
        locationOfYield = len(listPeriodKeyNameMain)
        for listOneItem in featureSetList:
            if listOneItem[locationOfYield] <= lowerUpper and listOneItem[locationOfYield] >= lowerLower:
                listOneItem[locationOfYield] = 1
                listOutputFeatureSet.append(listOneItem)
                #print(listOneItem[locationOfYield])
            elif listOneItem[locationOfYield] <= upperUpper and listOneItem[locationOfYield] >= upperLower:
                listOneItem[locationOfYield] = 0
                listOutputFeatureSet.append(listOneItem)
                #print(listOneItem[locationOfYield])
        return listOutputFeatureSet



    def obtainOneWholeTrainingFeatureSet(self, strStartYearMonth, strEndYearMonth, periodTypeStr, offsetDayNum, listPeriodKeyNameMain, intQuantileNum, strFeatureVersionNum, fileType, intLowerLowerPercentile, intRangePercentile):
        objPeriodFactorGenFunc = PeriodFactorGeneralFunctions()

        listHeader = []
        listHeader.append('id')
        for headerKeyItem in listPeriodKeyNameMain:
            listHeader.append(str(headerKeyItem))
        keyNum = len(listPeriodKeyNameMain)

        listHeader[keyNum] = 'yield_class'

        totalTransDateList, allPeriodPointDateList = objPeriodFactorGenFunc.RetrieveAllPeriodPointDateList(self.colTransDates, periodTypeStr)
        dtStartDate = datetime.datetime.strptime(strStartYearMonth, "%Y%m")
        dtEndDate = datetime.datetime.strptime(strEndYearMonth, "%Y%m")
        listToUpdatePeriodDayList = []
        for i in range(0, len(allPeriodPointDateList)):
            if allPeriodPointDateList[i] > (dtStartDate + relativedelta(months=-1)) and allPeriodPointDateList[i] < dtEndDate:
                listToUpdatePeriodDayList.append(allPeriodPointDateList[i].strftime('%Y%m%d'))
        listAllPeriodTrainingFeature = []
        listAllPeriodTrainingFeature.append(listHeader)
        for strInputDate in listToUpdatePeriodDayList:
            listOnePeriodFeature = self.obtainOnePeriodTrainingDataFile(strInputDate, periodTypeStr, offsetDayNum, listPeriodKeyNameMain, intQuantileNum, strFeatureVersionNum, fileType, intLowerLowerPercentile, intRangePercentile)
            for items in listOnePeriodFeature:
                listAllPeriodTrainingFeature.append(items)
            print('one month training feature included:' + strInputDate)
        return listAllPeriodTrainingFeature


    def obtainTrainingPeriodStarEndDict(self, strStartMonth, strEndMonth, strPeriodType, trainingPeriodNumber, numOffsetDay):
        objPeriodFactorGenFunc = PeriodFactorGeneralFunctions()
        totalTransDateList, allPeriodPointDateList = objPeriodFactorGenFunc.RetrieveAllPeriodPointDateList(self.colTransDates, strPeriodType)
        periodDateIndexList = []
        nextTransDateList = []
        for perdioDateItem in allPeriodPointDateList:
            periodDateIndexList.append(totalTransDateList.index(perdioDateItem))

        for perioDateIndex in periodDateIndexList:
            try:
                nextTransDateStr = str(totalTransDateList[perioDateIndex + 1].year) + str(totalTransDateList[perioDateIndex + 1].month)
                dtNextTransDate = datetime.datetime.strptime(nextTransDateStr, "%Y%m")
                nextTransDateList.append(dtNextTransDate)
            except IndexError:
                next
            #datetime.datetime.strptime(strStartYearMonth, "%Y%m")




        dtStartDate = datetime.datetime.strptime(strStartMonth, "%Y%m")
        dtEndDate = datetime.datetime.strptime(strEndMonth, "%Y%m")
        indexOfStartMonth = nextTransDateList.index(dtStartDate)
        indexOfEndMonth = nextTransDateList.index(dtEndDate)
        dictStartAndEndMonths = {}
        for i in range (indexOfStartMonth, indexOfEndMonth - trainingPeriodNumber+1):
            strOneStartMonth = allPeriodPointDateList[i+1].strftime('%Y%m')
            dictStartAndEndMonths[strOneStartMonth] = allPeriodPointDateList[i+trainingPeriodNumber].strftime('%Y%m')
        return dictStartAndEndMonths



    def writeUpdateOneTrainingFile(self, featureVersionNum, listKeyName, strStartPeriodMonth, strEndPeriodMonth, strPeriodType, numOffsetDays, intLowerLowerPercentile, intRangePercentile, trainingPeriodNumber):



        fileType = 'training'
        #trainingPeriodNumber = 12
#        for (k,v) in self.dictTrainFeatureSet.items():

#            featureVersionNum = int(k)
#            listKeyName = v
        fileName = self.createTrainingFeatureDataFileName(strStartPeriodMonth, strEndPeriodMonth, strPeriodType, numOffsetDays,
                                                              featureVersionNum, fileType, trainingPeriodNumber,
                                                              intLowerLowerPercentile, intRangePercentile)
        featureData = self.obtainOneWholeTrainingFeatureSet(strStartPeriodMonth, strEndPeriodMonth, strPeriodType, numOffsetDays, listKeyName, self.percentileNumber,
                                     featureVersionNum, fileType, intLowerLowerPercentile, intRangePercentile)

        with open(fileName, 'w') as csvfile:
            writer = csv.writer(csvfile, delimiter=',', lineterminator='\n')
            writer.writerows(featureData)

        print('Finished writing training file of feature number: '+ str(featureVersionNum) + ' , which contains: ',  str(listKeyName))


    def writeUpdateAllFeaturesTrainingFiles(self, strStartMonth, strEndMonth, strPeriodType, numOffsetDays):
        listTrainingSettingParameters = self.createTrainingSettingParameterList()
        for (k,v) in self.dictTrainFeatureSet.items():
            featureVersionNum = int(k)
            listKeyName = v
            for traingSettingParameters in listTrainingSettingParameters:
                intLowerLowerPercentile = traingSettingParameters[0]
                intRangePercentile = traingSettingParameters[1]
                trainingPeriodNumber = traingSettingParameters[2]
                dictPeriodStartAndEnd = self.obtainTrainingPeriodStarEndDict(strStartMonth, strEndMonth, strPeriodType, trainingPeriodNumber, numOffsetDays)
                for (k1, v1) in dictPeriodStartAndEnd.items():
                    trainStartMonth = str(k1)
                    trainEndMonth = str(v1)

                    self.writeUpdateOneTrainingFile(featureVersionNum, listKeyName, trainStartMonth, trainEndMonth, strPeriodType, numOffsetDays, intLowerLowerPercentile, intRangePercentile, trainingPeriodNumber)

    def createTrainingSettingParameterList(self):
        listTrainingSettingParamters = []

        # ### 6 items for training period of 3 months ####
        # listTrainingSettingParamter1=[1, 15, 3]
        # listTrainingSettingParamter2 = [3, 15, 3]
        # listTrainingSettingParamter3=[1, 20, 3]
        # listTrainingSettingParamter4 = [3, 20, 3]
        # listTrainingSettingParamter5=[1, 25, 3]
        # listTrainingSettingParamter6 = [3, 25, 3]
        # listTrainingSettingParamters.append(listTrainingSettingParamter1)
        # listTrainingSettingParamters.append(listTrainingSettingParamter2)
        # listTrainingSettingParamters.append(listTrainingSettingParamter3)
        # listTrainingSettingParamters.append(listTrainingSettingParamter4)
        # listTrainingSettingParamters.append(listTrainingSettingParamter5)
        # listTrainingSettingParamters.append(listTrainingSettingParamter6)
        # ### 6 items for training period of 3 months ####


        ### 2 items for training period of 6 months ####
        listTrainingSettingParamter1=[1, 15, 6]
        listTrainingSettingParamter2 = [3, 15, 6]
        ### 2 items for training period of 6 months ####


        # ### 2 items for training period of 12 months ####
        # listTrainingSettingParamter1 = [1, 15, 12]
        # listTrainingSettingParamter2 = [3, 15, 12]
        # ### 2 items for training period of 12 months ####

        # #### 2 items for training period of 24 months ####
        # listTrainingSettingParamter1 = [1, 15, 24]
        # listTrainingSettingParamter2 = [3, 15, 24]
        # #### 2 items for training period of 24 months ####

        listTrainingSettingParamters.append(listTrainingSettingParamter1)
        listTrainingSettingParamters.append(listTrainingSettingParamter2)

        # #include these only for training period of 3 months
        # listTrainingSettingParamters.append(listTrainingSettingParamter3)
        # listTrainingSettingParamters.append(listTrainingSettingParamter4)
        # listTrainingSettingParamters.append(listTrainingSettingParamter5)
        # listTrainingSettingParamters.append(listTrainingSettingParamter6)
        # #include these only for training period of 3 months

        return listTrainingSettingParamters


obj = CreatePeriodDatase()

#############################################
# 数据输入日期一定要为待预测周期的第一天（对于月换仓，不需要加日）
# strStartMonth = '201202' 代表为2012年1月最后一个交易日的特征数据，用于预测2012年2月末收益
# strEndMonth = '201707'代表为2017年6月最后一个交易日的特征数据，用于预测2012年7月末收益
# 数据输入日期一定要为待预测周期的第一天（对于月换仓，不需要加日）
#############################################

#####################################################################数值说明#####################################################################
#对于测试数据更新，例如要生成2017年8月票池，应设为 obj.writeUpdateAllTestingFeatureSet('201707', '201708', 'M', 0)
#obj.writeUpdateAllTestingFeatureSet('201708', '201709', 'M', 0)


#对于训练数据更新，例如要生成2017年8月票池，对于3个月训练期数据，应设为 obj.writeUpdateAllFeaturesTrainingFiles('201705', '201708', 'M', 0)

#####################################################################数值说明#####################################################################
#对于训练数据更新，例如要生成2017年8月票池，对于3个月训练期数据，应设为 obj.writeUpdateAllFeaturesTrainingFiles('201705', '201708', 'M', 0)
#对于训练数据更新，例如要生成2017年8月票池，对于6个月训练期数据，应设为 obj.writeUpdateAllFeaturesTrainingFiles('201702', '201708', 'M', 0)
#对于训练数据更新，例如要生成2017年8月票池，对于12个月训练期数据，应设为 obj.writeUpdateAllFeaturesTrainingFiles('201608', '201708', 'M', 0)
#对于训练数据更新，例如要生成2017年8月票池，对于24个月训练期数据，应设为 obj.writeUpdateAllFeaturesTrainingFiles('201508', '201708', 'M', 0)
#####################################################################数值说明#####################################################################

obj.writeUpdateAllFeaturesTrainingFiles('201703', '201709', 'M', 0)

